home *** CD-ROM | disk | FTP | other *** search
- Subject: v08i001: Georgia Tech 'se' Screen Editor
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: emoryu1!arnold (Arnold D. Robbins)
- Mod.sources: Volume 8, Issue 1
- Archive-name: se/Part01
-
-
- Here is the second release of the Georgia Tech Screen Editor, 'se'.
- There were enough changes that a whole new posting is warranted.
-
- Major Changes:
- All Georgia Tech specific stuff removed.
- It understands window size changes on 4.3BSD and ATT Unix PC/3B1
- Support for the shared library on the ATT Unix PC/3B1
- Considerable source code reorganization in certain files.
-
- Enjoy,
-
- Arnold Robbins
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # README
- # ascii.h
- # constdefs.h
- # docmd1.c
- # docmd2.c
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'README'" '(6131 characters)'
- if test -f 'README'
- then
- echo shar: will not over-write existing file "'README'"
- else
- cat << \SHAR_EOF > 'README'
- #
- # $Header: README,v 1.3 86/07/17 17:52:23 arnold Exp $
- #
- # $Log: README,v $
- # Revision 1.3 86/07/17 17:52:23 arnold
- # Fixed some spelling mistakes.
- #
- # Revision 1.2 86/07/17 17:19:06 arnold
- # Removed GT specific stuff, added discussion of window sensitivities.
- #
- # Revision 1.1 86/05/06 13:34:09 osadr
- # Initial revision
- #
- #
- #
- README:
-
- This directory contains the source files for the Unix version of the Georgia
- Tech Screen Editor "Se". It has three subdirectories which contain things
- that se needs. Here is a rundown of the various files.
-
- Files containing documentation are:
-
- README -- this file.
- se.m4 -- nroff manual page for se (has to be munged to create se.1).
- scriptse.1 -- nroff manual page for scriptse.
-
- The header files are:
-
- ascii.h -- definition of ASCII mnemonics and control characters.
- extern.h -- external data definitions for the screen editor.
- se.h -- global #define's for the screen editor.
- constdefs.h -- global constants, also used by files in subdirectories.
-
- The C source files are:
-
- main.c -- main program and declaration of globals, initialization.
- edit.c -- main command loop to get and execute commands, file handling.
- docmd1.c -- command decoder and functions for most commands.
- docmd2.c -- functions for the rest of the commands.
- misc.c -- miscellanious functions.
- scratch.c -- scratch file manipulating functions.
- screen.c -- routines to keep track of the screen contents.
- term.c -- routines for changing the terminal.
-
- The subdirectories are:
-
- libchangetty -- routines to change the terminal driver back and forth.
- pat -- pattern matching routines.
- se_h -- contains help scripts for all commands in se.
-
- Miscellanious files:
-
- where -- shell file to determine System V (R 1 or 2), 4.1, or 4.2 BSD.
- m4munge -- manipulate output of where for m4 for se man page
- makefile -- the makefile for make(1).
- print2 -- inode used by make for printing only changed stuff.
-
- scriptse.c -- quick and dirty C program to make scripts for se.
- scriptse.1 -- manual page for same.
-
- Executable files:
-
- se -- executable version of the screen editor.
- scriptse -- the executable version of the script maker.
-
-
- Conditional Compilation flags:
-
- The flag HARD_TERMS, if added to the CFLAGS macro in the makefile,
- will remove the terminal-independent code which uses termlib, and put back
- the original, terminal-types-hardwired-into-the-program code. The only
- reason to do this is if se has to run on a system without the termlib package.
- Using termlib, se is considerably smaller, as well as more flexible.
-
- The flag OLD_SCRATCH, if added to the CFLAGS macro in the makefile,
- will cause se to use the original, linked-list method for keeping track of
- lines in the buffer. This method is faster for rearranging lines, but
- considerably slower for simply looking up lines. Currently, se uses the
- method given in Software Tools in Pascal, which keeps the lines in order in
- an array. It is slower at rearranging, but as fast as possible for finding
- lines in the buffer. This version also takes less data and code space.
-
- The flag OLD_GLOB, if added to the CFLAGS macro in the makefile,
- will keep se from special casing commands whose effect is to reverse the
- order of the lines in the buffer. The special casing code can save an
- *incredible* amount of time for this pathological case, so it is best to leave
- things alone. This only applies to the Software Tools in Pascal style
- line handling.
-
- The flag LOG_USAGE, if added to the CFLAGS macro in the makefile,
- will cause se to write usage "statistics" to a log file, consisting of the
- login name and time and date when an individual used se. The logfile path
- name in the log() routine in edit.c should be changed to use a system
- accounting file somewhere. It currently creates a file in /usr/tmp.
-
- The 'where' command creates a file called 'flags', which the makefile
- cats inside ``s. These define and/or undefine the flags USG for System V,
- S5R2 if for Release 2, BSD for 4.1 and 4.2, and BSD4_2 for 4.2 specific code.
-
- Miscellanious:
-
- Code which is dependent on the Berkeley job control stuff is also
- conditionally compiled in, so that on systems without it, it won't get in
- the way.
-
- Code has been added which should allow se to come up under USG Unix
- 5.0 (System V). If S5R2 is defined, se will use the terminfo package.
- Otherwise, it assumes Release 1, and that the BSD termlib package has
- been ported and is available.
-
- There is code in term.c to test if se is running on a system with
- windows or not. It currently understands the windows on an ATT Unix PC (or 3B1)
- and the windowing ioctl's in BRL Unix, which should be identical to those
- in 4.3 BSD.
-
- Comments:
-
- It is a big piece of software. But, if you 1) read both Software Tools
- and Software Tools in Pascal (the chapters on editing and pattern matching, if
- you don't want to read all of the books), and 2) take your time, you should be
- able to understand, and eventually make changes to it, as necessary.
-
- Authors:
-
- Se started out as the version of 'ed' that came with the book 'Software
- Tools', by Kernighan and Plauger, which was written in Ratfor. On the Pr1me
- computers at the School of Information and Computer Science at Georgia Tech,
- Dan Forsyth, Perry Flinn, and Alan Akin added all the enhancements suggested
- in the exercises in the book, and some more of their own. Jack Waugh made
- extensive modifications to turn it into a screen editor; further work was done
- by Dan Forsyth. All of this was in an improved Georgia Tech version of Ratfor.
-
- Later, Dan Forsyth, then (and now) at Medical Systems Development
- Corporation, converted the Ratfor version into C, for Berkeley Unix (4.1 BSD).
- At Georgia Tech, Arnold Robbins took the C version and added many new features
- and improvements, the most important of which was termcap support and System V
- support. The existing help screens were edited and completed at that time, as
- well. This was completed in early 1985.
-
- Arnold Robbins is now at ...!gatech!emory!arnold, and will make every
- reasonable attempt to answer any questions anyone may have about it, but in
- no way promises to support or enhance 'se'.
- SHAR_EOF
- fi # end of overwriting check
- echo shar: extracting "'ascii.h'" '(1389 characters)'
- if test -f 'ascii.h'
- then
- echo shar: will not over-write existing file "'ascii.h'"
- else
- cat << \SHAR_EOF > 'ascii.h'
- /*
- * $Header: ascii.h,v 1.1 86/05/06 13:35:19 osadr Exp $
- */
-
- /*
- * $Log: ascii.h,v $
- * Revision 1.1 86/05/06 13:35:19 osadr
- * Initial revision
- *
- *
- */
-
- /*
- ** ascii.h
- **
- ** definitions of ASCII mnemonics and synonyms.
- */
-
- #ifndef _ASCII_H
- #define _ASCII_H
- #define NUL '\0'
- #define SOH '\001'
- #define STX '\002'
- #define ETX '\003'
- #define EOT '\004'
- #define ENQ '\005'
- #define ACK '\006'
- #define BEL '\007'
- #define BS '\010'
- #define HT '\011'
- #define LF '\012'
- #define VT '\013'
- #define FF '\014'
- #define CR '\015'
- #define SO '\016'
- #define SI '\017'
- #define DLE '\020'
- #define DC1 '\021'
- #define DC2 '\022'
- #define DC3 '\023'
- #define DC4 '\024'
- #define NAK '\025'
- #define SYN '\026'
- #define ETB '\027'
- #define CAN '\030'
- #define EM '\031'
- #define SUB '\032'
- #define ESC '\033'
- #define FS '\034'
- #define GS '\035'
- #define RS '\036'
- #define US '\037'
- #define SP '\040'
- #define DEL '\177'
- #define CTRL_A SOH
- #define CTRL_B STX
- #define CTRL_C ETX
- #define CTRL_D EOT
- #define CTRL_E ENQ
- #define CTRL_F ACK
- #define CTRL_G BEL
- #define CTRL_H BS
- #define CTRL_I HT
- #define CTRL_J LF
- #define CTRL_K VT
- #define CTRL_L FF
- #define CTRL_M CR
- #define CTRL_N SO
- #define CTRL_O SI
- #define CTRL_P DLE
- #define CTRL_Q DC1
- #define CTRL_R DC2
- #define CTRL_S DC3
- #define CTRL_T DC4
- #define CTRL_U NAK
- #define CTRL_V SYN
- #define CTRL_W ETB
- #define CTRL_X CAN
- #define CTRL_Y EM
- #define CTRL_Z SUB
- #endif
- SHAR_EOF
- fi # end of overwriting check
- echo shar: extracting "'constdefs.h'" '(325 characters)'
- if test -f 'constdefs.h'
- then
- echo shar: will not over-write existing file "'constdefs.h'"
- else
- cat << \SHAR_EOF > 'constdefs.h'
- /*
- * $Header: constdefs.h,v 1.1 86/05/06 13:35:37 osadr Exp $
- */
-
- /*
- * $Log: constdefs.h,v $
- * Revision 1.1 86/05/06 13:35:37 osadr
- * Initial revision
- *
- *
- */
-
- /*
- ** constdefs.h
- **
- ** Standard macro definitions for se screen editor
- */
-
- #define EOS '\0'
- #define ERR (-3)
- #define OK (-2)
- #define NO 0
- #define YES 1
- SHAR_EOF
- fi # end of overwriting check
- echo shar: extracting "'docmd1.c'" '(27523 characters)'
- if test -f 'docmd1.c'
- then
- echo shar: will not over-write existing file "'docmd1.c'"
- else
- cat << \SHAR_EOF > 'docmd1.c'
- #ifndef lint
- static char RCSid[] = "$Header: docmd1.c,v 1.3 86/07/17 17:19:37 arnold Exp $";
- #endif
-
- /*
- * $Log: docmd1.c,v $
- * Revision 1.3 86/07/17 17:19:37 arnold
- * Some general code cleaning up.
- *
- * Revision 1.2 86/07/11 15:10:20 osadr
- * Removed Georgia Tech specific items.
- *
- * Revision 1.1 86/05/06 13:36:44 osadr
- * Initial revision
- *
- *
- */
-
- /*
- ** docmd1.c
- **
- ** main command processor. routines for individual commands
- */
-
- #include "se.h"
- #include "extern.h"
-
- /* static data definitions -- variables only needed in this file */
- static char Tlpat[MAXPAT] = ""; /* saved character list for y/t command */
- static char Tabstr[MAXLINE] = ""; /* string representation of tab stops */
- static char Ddir = FORWARD; /* delete direction */
- static int Compress; /* compress/expand tabs on read/write */
-
- /* docmd --- handle all commands except globals */
-
- int docmd (lin, i, glob, status)
- char lin[];
- int i, glob, *status;
- {
- char file[MAXLINE], sub[MAXPAT];
- char kname;
- int gflag, line3, pflag, flag, fflag, junk, allbut, tflag;
- int append (), ckchar (), ckp (), ckupd (), copy ();
- int delete (), domark (), doopt (), doprnt (), doread ();
- int doshell ();
- int dotlit (), doundo (), dowrit (), getfn (), getkn ();
- int getone (), getrange (), getrhs (), getstr (), inject ();
- int join (), makset (), move (), nextln (), optpat ();
- int prevln (), substr (), draw_box ();
- char *expand_env ();
-
-
- *status = ERR;
- if (intrpt ()) /* catch a pending interrupt */
- return (*status);
-
- switch (lin[i]) {
- case APPENDCOM:
- case UCAPPENDCOM:
- if (lin[i + 1] == '\n' || lin[i + 1] == ':')
- {
- defalt (Curln, Curln);
- if (lin[i + 1] == '\n')
- {
- /* avoid updating with inline insertion */
- adjust_window (Line1, Line2);
- updscreen ();
- }
- *status = append (Line2, &lin[i + 1]);
- }
- break;
-
- case PRINTCUR:
- if (lin[i + 1] == '\n')
- {
- defalt (Curln, Curln);
- saynum (Line2);
- *status = OK;
- }
- break;
-
- case OVERLAYCOM:
- case UCOVERLAYCOM:
- defalt (Curln, Curln);
- if (lin[i + 1] == '\n')
- overlay (status);
- break;
-
- case CHANGE:
- case UCCHANGE:
- defalt (Curln, Curln);
- if (Line1 <= 0)
- Errcode = EORANGE;
- else if (lin[i + 1] == '\n' || lin[i + 1] == ':')
- {
- if (lin[i + 1] == '\n')
- {
- /* avoid updating with inline insertion */
- adjust_window (Line2, Line2);
- updscreen ();
- }
- First_affected = min (First_affected, Line1);
- if (lin[i + 1] == '\n')
- warn_deleted (Line1, Line2);
- *status = append (Line2, &lin[i + 1]);
- if (*status != ERR)
- {
- line3 = Curln;
- delete (Line1, Line2, status);
- Curln = line3 - (Line2 - Line1 + 1);
- /* adjust for deleted lines */
- }
- }
- break;
-
- case DELCOM:
- case UCDELCOM:
- if (ckp (lin, i + 1, &pflag, status) == OK)
- {
- defalt (Curln, Curln);
- if (delete (Line1, Line2, status) == OK
- && Ddir == FORWARD
- && nextln (Curln) != 0)
- Curln = nextln (Curln);
- }
- break;
-
- case INSERT:
- case UCINSERT:
- defalt (Curln, Curln);
- if (Line1 <= 0)
- Errcode = EORANGE;
- else if (lin[i + 1] == '\n' || lin[i + 1] == ':')
- {
- if (lin[i + 1] == '\n')
- {
- /* avoid updating with inline insertion */
- adjust_window (Line1, Line2);
- updscreen ();
- }
- *status = append (prevln (Line2), &lin[i + 1]);
- }
- break;
-
- case MOVECOM:
- case UCMOVECOM:
- i++;
- if (getone (lin, &i, &line3, status) == EOF)
- *status = ERR;
- if (*status == OK && ckp (lin, i, &pflag, status) == OK)
- {
- defalt (Curln, Curln);
- *status = move (line3);
- }
- break;
-
- case COPYCOM:
- case UCCOPYCOM:
- i++;
- if (getone (lin, &i, &line3, status) == EOF)
- *status = ERR;
- if (*status == OK && ckp (lin, i, &pflag, status) == OK)
- {
- defalt (Curln, Curln);
- *status = copy (line3);
- }
- break;
-
- case SUBSTITUTE:
- case UCSUBSTITUTE:
- i++;
- if (lin[i] == '\n')
- {
- /* turn "s\n" into "s//%/\n" */
- lin[i+0] = '/';
- lin[i+1] = '/';
- lin[i+2] = '%';
- lin[i+3] = '/';
- lin[i+4] = '\n';
- lin[i+5] = EOS;
- Peekc = SKIP_RIGHT;
- }
- else
- {
- /* try to handle "s/stuff\n" */
- int j, missing_delim;
-
- missing_delim = YES;
- for (j = i + 1; lin[j] != '\n'; j++)
- if (lin[j] == ESCAPE && lin[j+1] == lin[i])
- j++; /* skip esc, loop continues */
- else if (lin[j] == lin[i])
- {
- missing_delim = NO;
- break; /* for */
- }
-
- if (missing_delim)
- {
- for (; lin[j] != EOS; j++)
- ;
- j--; /* j now at newline */
-
- lin[j] = lin[i]; /* delim */
- lin[++j] = '\n';
- lin[++j] = EOS;
- Peekc = SKIP_RIGHT;
- /* rest of routines will continue to fix up */
- }
- }
-
- if (optpat (lin, &i) == OK
- && getrhs (lin, &i, sub, &gflag) == OK
- && ckp (lin, i + 1, &pflag, status) == OK)
- {
- defalt (Curln, Curln);
- *status = subst (sub, gflag, glob);
- }
- break;
-
- case TLITCOM:
- case UCTLITCOM:
- i++;
- if (lin[i] == '\n')
- {
- /* turn "y\n" into "y//%/\n" */
- lin[i+0] = '/';
- lin[i+1] = '/';
- lin[i+2] = '%';
- lin[i+3] = '/';
- lin[i+4] = '\n';
- lin[i+5] = EOS;
- Peekc = SKIP_RIGHT;
- }
- else
- {
- /* try to handle "y/stuff\n" */
- int j, missing_delim;
-
- missing_delim = YES;
- for (j = i + 1; lin[j] != '\n'; j++)
- if (lin[j] == ESCAPE && lin[j+1] == lin[i])
- j++; /* skip esc, loop continues */
- else if (lin[j] == lin[i])
- {
- missing_delim = NO;
- break; /* for */
- }
-
- if (missing_delim)
- {
- for (; lin[j] != EOS; j++)
- ;
- j--; /* j now at newline */
-
- lin[j] = lin[i]; /* delim */
- lin[++j] = '\n';
- lin[++j] = EOS;
- Peekc = SKIP_RIGHT;
- /* rest of routines will continue to fix up */
- }
- }
-
- if (getrange (lin, &i, Tlpat, MAXPAT, &allbut) == OK
- && makset (lin, &i, sub, MAXPAT) == OK
- && ckp (lin, i + 1, &pflag, status) == OK)
- {
- defalt (Curln, Curln);
- *status = dotlit (sub, allbut);
- }
- break;
-
- case JOINCOM:
- case UCJOINCOM:
- i++;
- if (getstr (lin, &i, sub, MAXPAT) == OK
- && ckp (lin, i + 1, &pflag, status) == OK)
- {
- defalt (prevln (Curln), Curln);
- *status = join (sub);
- }
- break;
-
- case UNDOCOM:
- case UCUNDOCOM:
- i++;
- defalt (Curln, Curln);
- if (ckchar (UCDELCOM, DELCOM, lin, &i, &flag, status) == OK
- && ckp (lin, i, &pflag, status) == OK)
- *status = doundo (flag, status);
- break;
-
- case ENTER:
- case UCENTER:
- i++;
- if (Nlines != 0)
- Errcode = EBADLNR;
- else if (ckupd (lin, &i, ENTER, status) == OK
- && ckchar ('x', 'X', lin, &i, &tflag, status) == OK)
- if (getfn (lin, i - 1, file) == OK)
- {
- strcpy (Savfil, expand_env (file));
- mesg (Savfil, FILE_MSG);
- clrbuf ();
- mkbuf ();
- dfltsopt (file);
- *status = doread (0, file, tflag);
- First_affected = 0;
- Curln = min (1, Lastln);
- Buffer_changed = NO;
- }
- else
- *status = ERR;
- break;
-
- case PRINTFIL:
- case UCPRINTFIL:
- if (Nlines != 0)
- Errcode = EBADLNR;
- else if (getfn (lin, i, file) == OK)
- {
- strcpy (Savfil, expand_env (file));
- mesg (Savfil, FILE_MSG);
- *status = OK;
- }
- break;
-
- case READCOM:
- case UCREADCOM:
- i++;
- if (ckchar ('x', 'X', lin, &i, &tflag, status) == OK)
- if (getfn (lin, i - 1, file) == OK)
- {
- defalt (Curln, Curln);
- *status = doread (Line2, file, tflag);
- }
- break;
-
- case WRITECOM:
- case UCWRITECOM:
- i++;
- flag = NO;
- fflag = NO;
- junk = ckchar ('>', '+', lin, &i, &flag, &junk);
- if (flag == NO)
- junk = ckchar ('!', '!', lin, &i, &fflag, &junk);
- junk = ckchar ('x', 'X', lin, &i, &tflag, &junk);
- if (getfn (lin, i - 1, file) == OK)
- {
- defalt (1, Lastln);
- *status = dowrit (Line1, Line2, file, flag, fflag, tflag);
- }
- break;
-
- case PRINT:
- case UCPRINT:
- if (lin[i + 1] == '\n')
- {
- defalt (1, Topln);
- *status = doprnt (Line1, Line2);
- }
- break;
-
- case PAGECOM:
- defalt (1, min (Lastln, Botrow - Toprow + Topln));
- if (Line1 <= 0)
- Errcode = EORANGE;
- else if (lin[i + 1] == '\n')
- {
- Topln = Line2;
- Curln = Line2;
- First_affected = Line2;
- *status = OK;
- }
- break;
-
- case NAMECOM:
- case UCNAMECOM:
- i++;
- if (getkn (lin, &i, &kname, DEFAULTNAME) != ERR
- && lin[i] == '\n')
- uniquely_name (kname, status);
- break;
-
- case MARKCOM:
- case UCMARKCOM:
- i++;
- if (getkn (lin, &i, &kname, DEFAULTNAME) != ERR
- && lin[i] == '\n')
- {
- defalt (Curln, Curln);
- *status = domark (kname);
- }
- break;
-
- case '\n':
- line3 = nextln (Curln);
- defalt (line3, line3);
- *status = doprnt (Line2, Line2);
- break;
-
- case LOCATECMD:
- case UCLOCATECMD:
- if (lin[i+1] == '\n')
- {
- char *sysname ();
-
- remark (sysname ());
- *status = OK;
- }
- break;
-
- case OPTCOM:
- case UCOPTCOM:
- if (Nlines == 0)
- *status = doopt (lin, &i);
- else
- Errcode = EBADLNR;
- break;
-
- case QUIT:
- case UCQUIT:
- i++;
- if (Nlines != 0)
- Errcode = EBADLNR;
- else if (ckupd (lin, &i, QUIT, status) == OK)
- if (lin[i] == '\n')
- *status = EOF;
- else
- *status = ERR;
- break;
-
- case HELP:
- case UCHELP:
- i++;
- if (Nlines == 0)
- dohelp (lin, &i, status);
- else
- Errcode = EBADLNR;
- break;
-
- case MISCCOM: /* miscellanious features */
- case UCMISCCOM:
- i++;
- switch (lin[i]) {
- case 'b': /* draw box */
- case 'B':
- defalt (Curln, Curln);
- i++;
- *status = draw_box (lin, &i);
- break;
-
- default:
- Errcode = EWHATZAT;
- break;
- }
- break;
-
- case SHELLCOM:
- i++;
- defalt (Curln, Curln);
- *status = doshell (lin, &i);
- break;
-
- default:
- Errcode = EWHATZAT; /* command not recognized */
- break;
- }
-
- if (*status == OK)
- Probation = NO;
-
- return (*status);
- }
-
-
- /* dohelp --- display documentation about editor */
-
- dohelp (lin, i, status)
- char lin[];
- int *i, *status;
- {
- char filename[MAXLINE];
- char swt_filename[MAXLINE];
- static char helpdir[] = "/usr/local/lib/se_h"; /* help scripts */
- int j;
- FILE *fp, *fopen ();
-
- SKIPBL (lin, *i);
- if (lin[*i] == NEWLINE)
- sprintf (filename, "%s/elp", helpdir);
- else
- {
- /* build filename from text after "h" */
- sprintf (filename, "%s/%s", helpdir, &lin[*i]);
- j = strlen (filename);
- filename[j-1] = EOS; /* lop off newline */
- }
-
- /* map to lower case */
- for (j = 0; filename[j] != EOS; j++)
- if (isupper (filename[j]))
- filename[j] = tolower (filename[j]);
-
- *status = OK;
- if ((fp = fopen (filename, "r")) == NULL)
- {
- *status = ERR;
- Errcode = ENOHELP;
- }
- else
- {
- #ifdef u3b2
- /* 3B2 seems to have problems with stdio and malloc... */
- char buf[BUFSIZ];
- setbuf (fp, buf);
- #endif
-
- /* status is OK */
- display_message (fp); /* display the help script */
- fclose (fp);
- }
- }
-
-
- /* doopt --- interpret option command */
-
- int doopt (lin, i)
- char lin[];
- int *i;
- {
- int temp, line, stat;
- char tempstr[4];
- int ret;
- int dosopt ();
- int ctoi ();
-
- (*i)++;
- ret = ERR;
-
- switch (lin[*i]) {
-
- case 'g': /* substitutes in a global can(not) fail */
- case 'G':
- if (lin[*i + 1] == '\n')
- {
- ret = OK;
- Globals = ! Globals; /* toggle */
- if (Globals == YES)
- remark ("failed global substitutes continue");
- else
- remark ("failed global substitutes stop");
- }
- break;
-
- case 'h':
- case 'H': /* do/don't use hardware insert/delete */
- if (lin[*i + 1] == '\n')
- {
- ret = OK;
- No_hardware = ! No_hardware;
- if (No_hardware == YES)
- remark ("no line insert/delete");
- else
- remark ("line insert/delete");
- }
- break;
-
- case 'k': /* tell user if buffer saved or not */
- case 'K':
- if (lin[*i + 1] == '\n')
- {
- ret = OK;
- if (Buffer_changed == YES)
- remark ("not saved");
- else
- remark ("saved");
- }
- break;
-
-
- case 'z': /* suspend the editor process */
- case 'Z':
- if (lin[*i + 1] == '\n')
- {
- ret = OK;
- #ifdef BSD
- if (Catching_stops)
- {
- if (Buffer_changed == YES)
- fprintf (stderr, "WARNING: buffer not saved\r\n");
- kill (getpid(), SIGTSTP);
- /* stop_hdlr() will do all the work for us */
- }
- #else
- remark ("process suspension not available");
- #endif
- }
- break;
-
- case 't': /* set or display tab stops for expanding tabs */
- case 'T':
- ++(*i);
- if (lin[*i] == '\n')
- {
- remark (Tabstr);
- ret = OK;
- }
- else
- {
- ret = settab (&lin[*i]);
- if (ret == OK)
- strcpy (Tabstr, &lin[*i]);
- else /* defaults were set */
- strcpy (Tabstr, "+4");
- }
- break;
-
- case 'w': /* set or display warning column */
- case 'W':
- ++(*i);
- if (lin[*i] == '\n')
- ret = OK;
- else
- {
- temp = ctoi (lin, i);
- if (lin[*i] == '\n')
- if (temp > 0 && temp < MAXLINE - 3)
- {
- ret = OK;
- Warncol = temp;
- }
- else
- Errcode = ENONSENSE;
- }
- if (ret == OK)
- saynum (Warncol);
- break;
-
- case '-': /* fix window in place on screen, or erase it */
- ++(*i);
- if (getnum (lin, i, &line, &stat) == EOF)
- {
- mesg ("", HELP_MSG);
- if (Toprow > 0)
- {
- Topln = max (1, Topln - Toprow);
- Toprow = 0;
- First_affected = Topln;
- }
- ret = OK;
- }
- else if (stat != ERR && lin[*i] == '\n')
- if (Toprow + (line - Topln + 1) < Cmdrow)
- {
- Toprow += line - Topln + 1;
- Topln = line + 1;
- for (temp = 0; temp < Ncols; temp++)
- load ('-', Toprow - 1, temp);
- if (Topln > Lastln)
- adjust_window (1, Lastln);
- if (Curln < Topln)
- Curln = min (Topln, Lastln);
- ret = OK;
- }
- else
- Errcode = EORANGE;
- break;
-
- case 'a': /* toggle absolute line numbering */
- case 'A':
- if (lin[*i + 1] == '\n')
- {
- Absnos = ! Absnos;
- ret = OK;
- }
- break;
-
- case 'c': /* toggle case option */
- case 'C':
- if (lin[*i + 1] == '\n')
- {
- ret = OK;
- Invert_case = ! Invert_case;
- if (Rel_a == 'A')
- {
- Rel_a = 'a';
- Rel_z = 'z';
- }
- else
- {
- Rel_a = 'A';
- Rel_z = 'Z';
- }
- }
-
- mesg (Invert_case ? "CASE" : "", CASE_MSG);
- break;
-
- case 'd': /* set or display placement of "." after a delete */
- case 'D':
- if (lin[*i + 1] == '\n')
- {
- if (Ddir == FORWARD)
- remark (">");
- else
- remark ("<");
- ret = OK;
- }
- else if (lin[*i + 2] != '\n')
- Errcode = EODLSSGTR;
- else if (lin[*i + 1] == '>')
- {
- ret = OK;
- Ddir = FORWARD;
- }
- else if (lin[*i + 1] == '<')
- {
- ret = OK;
- Ddir = BACKWARD;
- }
- else
- Errcode = EODLSSGTR;
- break;
-
- case 'v': /* set or display overlay column */
- case 'V':
- ++(*i);
- if (lin[*i] == '\n')
- {
- if (Overlay_col == 0)
- remark ("$");
- else
- saynum (Overlay_col);
- ret = OK;
- }
- else
- {
- if (lin[*i] == '$' && lin[*i + 1] == '\n')
- {
- Overlay_col = 0;
- ret = OK;
- }
- else
- {
- temp = ctoi (lin, i);
- if (lin[*i] == '\n')
- {
- Overlay_col = temp;
- ret = OK;
- }
- else
- Errcode = ENONSENSE;
- }
- }
- break;
-
- case 'u': /* set or display character for unprintable chars */
- case 'U':
- if (lin[*i + 1] == '\n')
- {
- ret = OK;
- tempstr[0] = tempstr[2] = '"';
- tempstr[1] = Unprintable;
- tempstr[3] = EOS;
- remark (tempstr);
- }
- else if (lin[*i + 2] == '\n')
- {
- if (lin[*i + 1] < ' ' || lin[*i + 1] >= DEL)
- Errcode = ENONSENSE;
- else
- {
- ret = OK;
- if (Unprintable != lin[*i + 1])
- {
- Unprintable = lin[*i + 1];
- First_affected = Topln;
- }
- }
- }
- break;
-
- case 'l': /* set or display line number display option */
- case 'L':
- if (lin[*i+1] == '\n')
- {
- Nchoise = EOS;
- ret = OK;
- }
- else if (lin[*i + 2] == '\n' &&
- (lin[*i + 1] == CURLINE || lin[*i + 1] == LASTLINE
- || lin[*i + 1] == TOPLINE))
- {
- Nchoise = lin[*i + 1];
- ret = OK;
- }
- else if (lin[*i + 1] == 'm' || lin[*i + 1] == 'M')
- {
- /* set or display the left margin */
- (*i)++;
- if (lin[*i + 1] == '\n')
- {
- saynum (Firstcol + 1);
- ret = OK;
- }
- else
- {
- (*i)++;
- temp = ctoi (lin, i);
- if (lin[*i] == '\n')
- if (temp > 0 && temp < MAXLINE)
- {
- First_affected = Topln;
- Firstcol = temp - 1;
- ret = OK;
- }
- else
- Errcode = ENONSENSE;
- }
- }
- break;
-
- case 'f': /* fortran (ugh, yick, gross) options */
- case 'F':
- if (lin[*i + 1] == '\n')
- ret = dosopt ("f");
- break;
-
- case 's': /* set source options */
- case 'S':
- ret = dosopt (&lin[*i + 1]);
- break;
-
- case 'i': /* set or display indent option */
- case 'I':
- ++(*i);
- if (lin[*i] == '\n')
- ret = OK;
- else if ((lin[*i] == 'a' || lin[*i] == 'A') && lin[*i + 1] == '\n')
- {
- Indent = 0;
- ret = OK;
- }
- else
- {
- temp = ctoi (lin, i);
- if (lin[*i] == '\n')
- if (temp > 0 && temp < MAXLINE - 3)
- {
- ret = OK;
- Indent = temp;
- }
- else
- Errcode = ENONSENSE;
- }
- if (ret == OK)
- if (Indent > 0)
- saynum (Indent);
- else
- remark ("auto");
- break;
-
- case 'm': /* toggle mail notification */
- case 'M':
- if (lin[*i + 1] == '\n')
- {
- Notify = ! Notify; /* toggle notification */
- remark (Notify ? "notify on" : "notify off");
- ret = OK;
- }
- break;
-
- case 'x':
- case 'X': /* toggle tab compression */
- if (lin[*i + 1] == '\n')
- {
- ret = OK;
- Compress = ! Compress;
- mesg (Compress ? "XTABS" : "", COMPRESS_MSG);
- }
- break;
-
- case 'y': /* encrypt files */
- case 'Y':
- if (lin[*i + 1] == '\n')
- {
- crypt_toggle:
- ret = OK;
- Crypting = ! Crypting;
- if (Crypting )
- do {
- getkey ();
- if (Key[0] == EOS)
- remark ("Empty keys are not allowed.\n");
- } while (Key[0] == EOS);
- else
- Key[0] = EOS;
- }
- else
- {
- register int j;
-
- ret = OK;
- (*i)++; /* *i was the 'y' */
- while (isspace (lin[*i]) && lin[*i] != '\n')
- (*i)++;
- if (lin[*i] != '\n' && lin[*i] != EOS)
- {
- for (j = 0; lin[*i] != '\n' && lin[*i] != EOS;
- j++, (*i)++)
- Key[j] = lin[*i];
- Key[j] = EOS;
- Crypting = YES;
- }
- else
- goto crypt_toggle;
- }
- mesg (Crypting ? "ENCRYPT" : "", CRYPT_MSG);
- break;
-
- default:
- Errcode = EOWHAT;
-
- }
-
- return (ret);
- }
-
-
- /* domark --- name lines line1 through line2 as kname */
-
- int domark (kname)
- char kname;
- {
- int line;
- int ret;
- register LINEDESC *k;
- LINEDESC *getind ();
-
- if (Line1 <= 0)
- {
- Errcode = EORANGE;
- ret = ERR;
- }
- else
- {
- k = getind (Line1);
- for (line = Line1; line <= Line2; line++)
- {
- if (intrpt())
- return (ERR);
- k -> Markname = kname;
- k = NEXTLINE(k);
- }
- ret = OK;
- }
- return (ret);
- }
-
-
- /* doprnt --- set curln, locate window */
-
- int doprnt (from, to)
- int from, to;
- {
-
- if (from <= 0)
- {
- Errcode = EORANGE;
- return (ERR);
- }
-
- adjust_window (from, to);
- Curln = to;
- return (OK);
- }
-
-
- /* doread --- read "file" after "line" */
-
- int doread (line, file, tflag)
- int line;
- char *file;
- int tflag;
- {
- register int count, len, i;
- int ret;
- int strlen ();
- FILE *fd;
- FILE *fopen (), *crypt_open ();
- char lin1[MAXLINE], lin2[MAXLINE];
- char *fgets ();
- register LINEDESC *ptr;
- LINEDESC *sp_inject ();
- LINEDESC *getind ();
- char *expand_env ();
-
- file = expand_env (file); /* expand $HOME, etc. */
-
- if (Savfil[0] == EOS)
- {
- strcpy (Savfil, file);
- mesg (Savfil, FILE_MSG);
- }
-
- if (Crypting)
- fd = crypt_open (file, "r");
- else
- fd = fopen (file, "r");
-
- if (fd == NULL)
- {
- ret = ERR;
- Errcode = ECANTREAD;
- }
- else
- {
- First_affected = min (First_affected, line + 1);
- ptr = getind (line);
- ret = OK;
- #ifndef OLD_SCRATCH
- Curln = line;
- #endif
- remark ("reading");
- for (count = 0; fgets (lin1, MAXLINE, fd) != NULL; count++)
- {
- if (intrpt ())
- {
- ret = ERR;
- break;
- }
- if (Compress == NO && tflag == NO)
- ptr = sp_inject (lin1, strlen (lin1), ptr);
- else
- {
- len = 0;
- for (i = 0; lin1[i] != EOS && len < MAXLINE - 1; i++)
- if (lin1[i] != '\t')
- lin2[len++] = lin1[i];
- else
- do
- lin2[len++] = ' ';
- while (len % 8 != 0
- && len < MAXLINE - 1);
- lin2[len] = EOS;
- if (len >= MAXLINE)
- {
- ret = ERR;
- Errcode = ETRUNC;
- }
- ptr = sp_inject (lin2, len, ptr);
- }
- if (ptr == NOMORE)
- {
- ret = ERR;
- break;
- }
- }
- if (Crypting)
- crypt_close (fd);
- else
- fclose (fd);
- saynum (count);
- Curln = line + count;
- svins (line, count);
- }
-
- return (ret);
- }
-
-
- /* dosopt --- set source language-related options */
-
- int dosopt (lin)
- char lin[];
- {
- char lang[8];
- int i;
- int strbsr ();
- static struct {
- char *txt;
- int val;
- } ltxt[] = {
- "", 1,
- "as", 2,
- "c", 3,
- "d", 1,
- "data", 1,
- "f", 4,
- "h", 3,
- "n", 1,
- "nr", 1,
- "nroff",1,
- "p", 3,
- "r", 3,
- "s", 2,
- };
-
- i = 0;
- getwrd (lin, &i, lang, 8);
-
- strmap (lang, 'a');
-
- i = strbsr ((char *)ltxt, sizeof (ltxt), sizeof (ltxt[0]), lang);
- if (i == EOF)
- {
- Errcode = ENOLANG;
- return (ERR);
- }
-
- /*
- * these are all the same under Unix, so factor
- * them out of the switch.
- */
-
- Rel_a = 'A';
- Rel_z = 'Z';
- Invert_case = NO;
- Compress = NO;
-
- switch (ltxt[i].val) {
- case 1:
- Warncol = 74;
- strcpy (Tabstr, "+4");
- break;
-
- case 2:
- Warncol = 72;
- strcpy (Tabstr, "17+8");
- Compress = YES; /* except this one */
- break;
-
- case 3:
- Warncol = 74;
- strcpy (Tabstr, "+8");
- break;
-
- case 4:
- Warncol = 72;
- strcpy (Tabstr, "7+3");
- break;
- }
-
- settab (Tabstr);
- mesg (Invert_case == YES ? "CASE" : "", CASE_MSG);
- mesg (Compress == YES ? "XTABS" : "", COMPRESS_MSG);
-
- return (OK);
- }
-
-
- /* dotlit --- transliterate characters */
-
- int dotlit (sub, allbut)
- char sub[];
- int allbut;
- {
- char new[MAXLINE];
- char kname;
- int collap, x, i, j, line, lastsub, status;
- int ret;
- LINEDESC *inx;
- LINEDESC *gettxt (), *getind ();
-
- ret = ERR;
- if (Line1 <= 0)
- {
- Errcode = EORANGE;
- return (ret);
- }
-
- if (First_affected > Line1)
- First_affected = Line1;
-
- lastsub = strlen (sub) - 1;
- if ((strlen (Tlpat) - 1) > lastsub || allbut == YES)
- collap = YES;
- else
- collap = NO;
-
- for (line = Line1; line <= Line2; line++)
- {
- if (intrpt ()) /* check for interrupts */
- return (ERR);
-
- inx = gettxt (line); /* get text of line into txt, return index */
- j = 0;
- for (i = 0; Txt[i] != EOS && Txt[i] != '\n'; i++)
- {
- x = xindex (Tlpat, Txt[i], allbut, lastsub);
- if (collap == YES && x >= lastsub && lastsub >= 0) /* collapse */
- {
- new[j] = sub[lastsub];
- j++;
- for (i++; Txt[i] != EOS && Txt[i] != '\n'; i++)
- {
- x = xindex (Tlpat, Txt[i], allbut, lastsub);
- if (x < lastsub)
- break;
- }
- }
- if (Txt[i] == EOS || Txt[i] == '\n')
- break;
- if (x >= 0 && lastsub >= 0) /* transliterate */
- {
- new[j] = sub[x];
- j++;
- }
- else if (x < 0) /* copy */
- {
- new[j] = Txt[i];
- j++;
- }
- /* else
- delete */
- }
-
- if (Txt[i] == '\n') /* add a newline, if necessary */
- {
- new[j] = '\n';
- j++;
- }
- new[j] = EOS; /* add the EOS */
-
- kname = inx -> Markname; /* save the markname */
- delete (line, line, &status);
- ret = inject (new);
- if (ret == ERR)
- break;
- inx = getind (Curln);
- inx -> Markname = kname; /* set markname */
- ret = OK;
- Buffer_changed = YES;
- }
-
- return (ret);
- }
-
- /* doundo --- restore last set of lines deleted */
-
- int doundo (dflg, status)
- int dflg;
- int *status;
- {
- LINEDESC *l1, *l2, *k1, *k2;
- LINEDESC *getind ();
- int oldcnt;
- int nextln (), prevln ();
-
- *status = ERR;
- if (dflg == NO && Line1 <= 0)
- Errcode = EORANGE;
- else if (Limbo == NOMORE)
- Errcode = ENOLIMBO;
- else if (Line1 > Line2)
- Errcode = EBACKWARD;
- else if (Line2 > Lastln)
- Errcode = ELINE2;
- else
- {
- *status = OK;
- Curln = Line2;
- #ifdef OLD_SCRATCH
- k1 = getind (Line2);
- k2 = getind (nextln (Line2));
- l1 = Limbo;
- l2 = l1 -> Prevline;
- relink (k1, l1, l2, k2);
- relink (l2, k2, k1, l1);
- #else
- blkmove (Limbo - Buf, MAXBUF - 1, Line2);
- #endif
- svins (Line2, Limcnt);
- oldcnt = Limcnt;
- Limcnt = 0;
- Limbo = NOMORE;
- Lastln += oldcnt;
- if (dflg == NO)
- delete (Line1, Line2, status);
- Curln += oldcnt;
- if (First_affected > Line1)
- First_affected = Line1;
- }
-
- return (*status);
- }
-
- /* dowrit --- write "from" through "to" into file */
-
- int dowrit (from, to, file, aflag, fflag, tflag)
- int from, to, aflag, fflag, tflag;
- char *file;
- {
- FILE *fd;
- FILE *fopen (), *crypt_open ();
- register int line, ret, i, j;
- int strcmp (), access ();
- char tabs[MAXLINE];
- register LINEDESC *k;
- LINEDESC *getind ();
- char *expand_env ();
-
- ret = ERR;
- if (from <= 0)
- Errcode = EORANGE;
-
- else
- {
- file = expand_env (file); /* expand $HOME, etc. */
-
- if (aflag == YES)
- {
- if (Crypting)
- fd = crypt_open (file, "a");
- else
- fd = fopen (file, "a");
- }
- else if (strcmp (file, Savfil) == 0 || fflag == YES
- || Probation == WRITECOM || access (file, 0) == -1)
- {
- if (Crypting)
- fd = crypt_open (file, "w");
- else
- fd = fopen (file, "w");
- }
- else
- {
- Errcode = EFEXISTS;
- Probation = WRITECOM;
- return (ret);
- }
- if (fd == NULL)
- Errcode = ECANTWRITE;
- else
- {
- ret = OK;
- remark ("writing");
- k = getind (from);
- for (line = from; line <= to; line++)
- {
- if (intrpt ())
- return (ERR);
- gtxt (k);
- if (Compress == NO && tflag == NO)
- fputs (Txt, fd);
- else
- {
- for (i = 0; Txt[i] == ' '; i++)
- ;
- for (j = 0; j < i / 8; j++)
- tabs[j] = '\t';
- tabs[j] = EOS;
- fputs (tabs, fd);
- fputs (&Txt[j * 8], fd);
- }
- k = NEXTLINE(k);
- }
- if (Crypting)
- crypt_close (fd);
- else
- fclose (fd);
- sync (); /* just in case the system crashes */
- saynum (line - from);
- if (from == 1 && line - 1 == Lastln)
- Buffer_changed = NO;
- }
- }
- return (ret);
- }
-
- /* expand_env --- expand environment variables in file names */
-
- char *expand_env (file)
- register char *file;
- {
- register int i, j, k; /* indices */
- char *getenv ();
- char var[MAXLINE]; /* variable name */
- char *val; /* value of environment variable */
- static char buf[MAXLINE * 2]; /* expanded file name, static to not go away */
-
-
- i = j = k = 0;
- while (file[i] != EOS)
- {
- if (file[i] == ESCAPE)
- {
- if (file[i+1] == '$')
- {
- buf[j++] = file[++i]; /* the actual $ */
- i++; /* for next time around the loop */
- }
- else
- buf[j++] = file[i++]; /* the \ */
- }
- else if (file[i] != '$') /* normal char */
- buf[j++] = file[i++];
- else /* environment var */
- {
- i++; /* skip $ */
- k = 0;
- while (file[i] != '/' && file[i] != EOS)
- var[k++] = file[i++]; /* get var name */
- var[k] = EOS;
-
- if ((val = getenv (var)) != NULL)
- for (k = 0; val[k] != EOS; k++)
- buf[j++] = val[k];
- /* copy val into file name */
- else if (file[i] == '/')
- i++; /* var not in enviroment; strip */
- /* extra slash */
- }
- }
- buf[j] = EOS;
-
- return (buf);
- }
-
- /* crypt_open -- run files through crypt */
-
- FILE *crypt_open (file, mode)
- char *file, *mode;
- {
- char buf[MAXLINE];
- FILE *fp, *popen ();
-
- if (! Crypting)
- return (NULL);
-
- while (Key[0] == EOS)
- {
- getkey ();
- if (Key[0] == EOS)
- fprintf (stderr, "The key must be non-empty!\r\n");
- }
-
- switch (mode[0]) {
- case 'r':
- sprintf (buf, "crypt %s < %s", Key, file);
- fp = popen (buf, "r");
- return (fp); /* caller checks for NULL or not */
- break;
-
- case 'w':
- sprintf (buf, "crypt %s > %s", Key, file);
- fp = popen (buf, "w");
- return (fp); /* caller checks for NULL or not */
- break;
-
- case 'a':
- sprintf (buf, "crypt %s >> %s", Key, file);
- fp = popen (buf, "w");
- return (fp); /* caller checks for NULL or not */
- break;
-
- default:
- return (NULL);
- }
- }
-
- crypt_close (fp)
- FILE *fp;
- {
- pclose (fp);
- }
-
- /* getkey -- get an encryption key from the user */
-
- #define repeat do
- #define until(cond) while(!(cond))
-
- getkey ()
- {
- char *getpass (); /* get input w/out echoing on screen */
-
- clrscreen (); /* does NOT wipe out Screen_image */
- tflush ();
-
- ttynormal ();
-
- repeat
- {
- strcpy (Key, getpass ("Enter encryption key: "));
- if (strcmp (Key, getpass ("Again: ")) != 0)
- {
- Key[0] = EOS;
- fprintf (stderr, "didn't work. try again.\n");
- }
- /* else
- all ok */
- } until (Key[0] != EOS);
-
- ttyedit ();
-
- restore_screen ();
- }
- SHAR_EOF
- fi # end of overwriting check
- echo shar: extracting "'docmd2.c'" '(18109 characters)'
- if test -f 'docmd2.c'
- then
- echo shar: will not over-write existing file "'docmd2.c'"
- else
- cat << \SHAR_EOF > 'docmd2.c'
- #ifndef lint
- static char RCSid[] = "$Header: docmd2.c,v 1.3 86/07/17 17:20:29 arnold Exp $";
- #endif
-
- /*
- * $Log: docmd2.c,v $
- * Revision 1.3 86/07/17 17:20:29 arnold
- * Some general code cleaning up.
- *
- * Revision 1.2 86/07/11 15:11:04 osadr
- * Removed Georgia Tech specific code.
- *
- * Revision 1.1 86/05/06 13:36:57 osadr
- * Initial revision
- *
- *
- */
-
- /*
- ** docmd2.c
- **
- ** routines to actually execute commands
- */
-
- #include "se.h"
- #include "extern.h"
-
-
- /* append --- append lines after "line" */
-
- append (line, str)
- int line;
- char str[];
- {
- char lin[MAXLINE];
- char term;
- int ret;
- int len, i, dpos, dotseen;
- int inject ();
-
- Curln = line;
-
- if (str[0] == ':') /* text to be added is in the command line */
- ret = inject (&str[1]);
- else
- {
- Cmdrow = Toprow + (Curln - Topln) + 1; /* 1 below Curln */
- lin[0] = EOS;
- if (Indent > 0 || line <= 0)
- len = max (0, Indent - 1);
- else /* do auto indent */
- {
- LINEDESC *k, *gettxt ();
- k = gettxt (line);
- for (len = 0; Txt[len] == ' '; len++)
- ;
- }
- dpos = len; /* position for terminating '.' */
-
- for (ret = NOSTATUS; ret == NOSTATUS; )
- {
- if (! hwinsdel()) /* do it the old, slow way */
- {
- if (Cmdrow > Botrow)
- {
- Cmdrow = Toprow + 1;
- cprow (Botrow, Toprow);
- adjust_window (Curln, Curln);
- if (First_affected > Topln)
- First_affected = Topln;
- }
- clrrow (Cmdrow);
- if (Cmdrow < Botrow)
- clrrow (Cmdrow + 1);
- }
- else /* try to be smart about it */
- {
- if (Cmdrow > Botrow)
- {
- Cmdrow--;
- dellines (Toprow, 1);
- inslines (Cmdrow, 1);
- Topln++;
- }
- else
- {
- dellines (Botrow, 1);
- inslines (Cmdrow, 1);
- }
- }
- prompt ("apd>");
- do
- getcmd (lin, Firstcol, &len, &term);
- while (term == CURSOR_UP || term == CURSOR_DOWN
- || term == CURSOR_SAME);
-
- dotseen = 0;
- if (lin[0] == '.' && lin[1] == '\n' && lin[2] == EOS)
- dotseen = 1;
- for (i = 0; i < dpos && lin[i] == ' '; i++)
- ;
- if (i == dpos && lin[dpos] == '.' && lin[dpos + 1] == '\n'
- && lin[dpos+2] == EOS)
- dotseen = 1;
-
- if (dotseen)
- {
- if (hwinsdel())
- {
- dellines (Cmdrow, 1);
- inslines (Botrow, 1);
- }
- ret = OK;
- }
- else if (inject (lin) == ERR)
- ret = ERR;
- else /* inject occured */
- prompt (""); /* erase prompt */
- Cmdrow++;
- if (term != FUNNY)
- {
- if (Indent > 0)
- len = Indent - 1;
- else /* do auto indent */
- for (len = 0; lin[len] == ' '; len++)
- ;
- dpos = len;
- lin[0] = EOS;
- }
- }
- Cmdrow = Botrow + 1;
- if (hwinsdel()) /* since we take control */
- { /* of the screen, we're sure */
- Sctop = Topln; /* it's still OK */
-
- for (i = 0; i < Sclen; i++)
- Scline[i] = Sctop + i <= Lastln ? i : -1;
- }
- }
- if (Curln == 0 && Lastln > 0) /* for 0a or 1i followed by "." */
- Curln = 1;
- if (First_affected > line)
- First_affected = line;
-
- tflush ();
- return (ret);
- }
-
- /* copy --- copy line1 through line2 after line3 */
-
- int copy (line3)
- int line3;
- {
- register int i;
- int ret;
- register LINEDESC *ptr3, *after3, *k;
- LINEDESC *getind ();
-
- ret = ERR;
-
- #ifdef OLD_SCRATCH
- ptr3 = getind (line3);
- after3 = ptr3 -> Nextline;
- #endif
-
- if (Line1 <= 0)
- Errcode = EORANGE;
- else
- {
- ret = OK;
- Curln = line3;
- k = getind (Line1);
- for (i = Line1; i <= Line2; i++)
- {
- gtxt (k);
- if (inject (Txt) == ERR || intrpt ())
- {
- ret = ERR;
- break;
- }
- #ifdef OLD_SCRATCH
- if (k == ptr3) /* make sure we don't copy stuff */
- k = after3; /* that's already been copied */
- else
- k = k -> Nextline;
- #else
- if (Line1 < line3)
- k++;
- else
- k += 2;
- /*
- * inject calls blkmove, which will shift the
- * lines down one in the array, so we add two
- * instead of one to get to the next line.
- */
- #endif
- }
- First_affected = min (First_affected, line3 + 1);
- }
- return (ret);
- }
-
-
- /* delete --- delete lines from through to */
-
- int delete (from, to, status)
- int from, to, *status;
- {
- int nextln (), prevln ();
- LINEDESC *k1, *k2, *j1, *j2, *l1;
- LINEDESC *getind ();
-
- if (from <= 0) /* can't delete line 0 */
- {
- *status = ERR;
- Errcode = EORANGE;
- }
- else
- {
- if (First_affected > from)
- First_affected = from;
- #ifdef OLD_SCRATCH
- k1 = getind (prevln (from));
- j1 = k1 -> Nextline;
- j2 = getind (to);
- k2 = j2 -> Nextline;
- relink (k1, k2, k1, k2); /* close chain around deletion */
- #else
- blkmove (from, to, MAXBUF - 1); /* stick at end of buffer */
- #endif
-
- Lastln -= to - from + 1; /* adjust number of last line */
- Curln = prevln (from);
-
- #ifdef OLD_SCRATCH
- if (Limbo != NOMORE) /* discard lines in limbo */
- {
- l1 = Limbo -> Prevline;
- Limbo -> Prevline = Free;
- Free = l1;
- }
- #endif
-
- Lost_lines += Limcnt;
- Limcnt = to - from + 1; /* number of lines "deleted" */
-
- #ifdef OLD_SCRATCH
- Limbo = j1; /* put what we just deleted in limbo */
- relink (j2, j1, j2, j1); /* close the ring */
- #else
- /* point at first deleted */
- Limbo = &Buf[MAXBUF - (to - from + 1)];
- #endif
- *status = OK;
- svdel (from, to - from + 1);
- Buffer_changed = YES;
- }
-
- return (*status);
- }
-
-
- /* join --- join a group of lines into a single line */
-
- int join (sub)
- char sub[];
- {
- char new[MAXLINE];
- register int l, line, sublen;
- int ret;
- int inject (), delete (), prevln (), strlen ();
- register LINEDESC *k;
- LINEDESC *getind ();
-
- ret = OK;
- if (Line1 <= 0)
- {
- Errcode = EORANGE;
- return (ERR);
- }
-
- sublen = strlen (sub) + 1; /* length of separator & EOS */
- line = Line1;
- k = getind (line);
- gtxt (k);
- move_ (Txt, new, (int) k -> Lineleng); /* move in first chunk */
- l = k -> Lineleng;
-
- for (line++; line <= Line2; line++)
- {
- if (intrpt ())
- return (ERR);
- if (new[l - 2] == '\n') /* zap the NEWLINE */
- l--;
- k = NEXTLINE(k); /* get the next line */
- gtxt (k);
- if (l + sublen - 1 + k -> Lineleng - 1 > MAXLINE) /* won't fit */
- {
- Errcode = E2LONG;
- return (ERR);
- }
- move_ (sub, &new[l - 1], sublen); /* insert separator string */
- l += sublen - 1;
- move_ (Txt, &new[l - 1], (int) k -> Lineleng); /* move next line */
- l += k -> Lineleng - 1;
- }
- Curln = Line2; /* all this will replace line1 through line2 */
- ret = inject (new); /* inject the new line */
- if (ret == OK)
- ret = delete (Line1, Line2, &ret); /* delete old lines */
- Curln++;
-
- if (First_affected > Curln)
- First_affected = Curln;
-
- return (ret);
- }
-
-
- /* move --- move line1 through line2 after line3 */
-
- int move (line3)
- int line3;
- {
- int nextln (), prevln ();
- LINEDESC *k0, *k1, *k2, *k3, *k4, *k5;
- LINEDESC *getind ();
-
- if (Line1 <= 0)
- {
- Errcode = EORANGE;
- return (ERR);
- }
-
- if (Line1 <= line3 && line3 <= Line2)
- {
- Errcode = EINSIDEOUT;
- return (ERR);
- }
-
- #ifdef OLD_SCRATCH
- k0 = getind (prevln (Line1));
- k1 = k0 -> Nextline;
- k2 = getind (Line2);
- k3 = k2 -> Nextline;
- relink (k0, k3, k0, k3);
- #else
- blkmove (Line1, Line2, line3);
- #endif
-
- if (line3 > Line1)
- {
- Curln = line3;
- #ifdef OLD_SCRATCH
- line3 -= Line2 - Line1 + 1;
- #endif
- }
- else
- Curln = line3 + (Line2 - Line1 + 1);
-
- #ifdef OLD_SCRATCH
- k4 = getind (line3);
- k5 = k4 -> Nextline;
- relink (k4, k1, k2, k5);
- relink (k2, k5, k4, k1);
- #endif
-
- Buffer_changed = YES;
- First_affected = min (First_affected, min (Line1, line3));
-
- return (OK);
- }
-
- /* overlay --- let user edit lines directly */
-
- overlay (status)
- int *status;
- {
- char savtxt[MAXLINE], term, kname;
- static char empty[] = "\n";
- int lng, vcol, lcurln, scurln;
- int inject (), nextln (), prevln (), strcmp ();
- LINEDESC *indx;
- LINEDESC *getind (), *gettxt ();
-
- *status = OK;
- if (Line1 == 0)
- {
- Curln = 0;
- *status = inject (empty);
- if (*status == ERR)
- return;
- First_affected = 1;
- Line1 = 1;
- Line2++;
- }
-
- for (lcurln = Line1; lcurln <= Line2; lcurln++)
- {
- Curln = lcurln;
- vcol = Overlay_col - 1;
- do {
- adjust_window (Curln, Curln);
- updscreen ();
- Cmdrow = Curln - Topln + Toprow;
- indx = gettxt (Curln);
- lng = indx -> Lineleng;
- if (Txt[lng - 2] == '\n') /* clobber newline */
- lng--;
- if (vcol < 0)
- vcol = lng - 1;
- while (lng - 1 < vcol)
- {
- Txt[lng - 1] = ' ';
- lng++;
- }
- Txt[lng - 1] = '\n';
- Txt[lng] = EOS;
- move_ (Txt, savtxt, lng + 1); /* make a copy of the line */
- getcmd (Txt, Firstcol, &vcol, &term);
- if (term == FUNNY)
- {
- if (First_affected > Curln)
- First_affected = Curln;
- Cmdrow = Botrow + 1;
- return;
- }
- if (strcmp (Txt, savtxt) != 0) /* was line changed? */
- {
- kname = indx -> Markname;
- delete (Curln, Curln, status);
- scurln = Curln;
- if (*status == OK)
- *status = inject (Txt);
- if (*status == ERR)
- {
- Cmdrow = Botrow + 1;
- return;
- }
- indx = getind (nextln (scurln));
- indx -> Markname = kname;
- }
- else
- { /* in case end-of-line is moved */
- if (First_affected > Curln)
- First_affected = Curln;
- }
- switch (term) {
- case CURSOR_UP:
- if (Curln > 1)
- Curln--;
- else
- Curln = Lastln;
- break;
- case CURSOR_DOWN:
- if (Curln < Lastln)
- Curln++;
- else
- Curln = min (1, Lastln);
- break;
- case CURSOR_SAME:
- vcol = 0;
- break;
- }
- } while (term == CURSOR_UP ||
- term == CURSOR_DOWN ||
- term == CURSOR_SAME);
- }
- Cmdrow = Botrow + 1;
- return;
- }
-
-
- /* subst --- substitute "sub" for occurrences of pattern */
-
- int subst (sub, gflag, glob)
- char sub[];
- int gflag, glob;
- {
- char new[MAXLINE], kname;
- register int line, m, k, lastm;
- int j, junk, status, subbed, ret;
- int tagbeg[10], tagend[10];
- int amatch (), addset (), inject ();
- register LINEDESC *inx;
- LINEDESC *gettxt (), *getind ();
-
- if (Globals && glob)
- ret = OK;
- else
- ret = ERR;
-
- if (Line1 <= 0)
- {
- Errcode = EORANGE;
- return (ERR);
- }
-
- /* the following code has been removed for your protection
- index() occasionally grabs newlines out of the character class
- counter in a pattern. for example [0-9] doesn't work due to this
-
- if (index (Pat, '\n') != -1) # never delete NEWLINE
- {
- Errcode = EBADPAT;
- return (ERR);
- }
- */
-
- for (line = Line1; line <= Line2; line++)
- {
- if (intrpt ())
- break;
- j = 0;
- subbed = NO;
- inx = gettxt (line);
- lastm = -1;
- for (k = 0; Txt[k] != EOS; )
- {
- for (m = 1; m <= 9; m++)
- {
- tagbeg[m] = -1;
- tagend[m] = -1;
- }
- if (gflag == YES || subbed == NO)
- m = amatch (Txt, k, Pat, &tagbeg[1], &tagend[1]);
- else
- m = -1;
- if (m > -1 && lastm != m) /* replace matched text */
- {
- subbed = YES;
- tagbeg[0] = k;
- tagend[0] = m;
- catsub (Txt, tagbeg, tagend, sub, new, &j, MAXLINE);
- lastm = m;
- }
- if (m == -1 || m == k) /* no match or null match */
- {
- junk = addset (Txt[k], new, &j, MAXLINE);
- k++;
- }
- else
- k = m; /* skip matched text */
- }
- if (subbed == YES)
- {
- if (addset (EOS, new, &j, MAXLINE) == NO)
- {
- ret = ERR;
- Errcode = E2LONG;
- break;
- }
- kname = inx -> Markname;
- delete (line, line, &status); /* remembers dot */
- ret = inject (new);
- if (First_affected > Curln)
- First_affected = Curln;
- if (ret == ERR)
- break;
- inx = getind (Curln);
- inx -> Markname = kname;
- ret = OK;
- Buffer_changed = YES;
- }
- else /* subbed == NO */
- Errcode = ENOMATCH;
- }
-
- return (ret);
- }
-
-
- /* uniquely_name --- mark-name line; make sure no other line has same name */
-
- uniquely_name (kname, status)
- char kname;
- int *status;
- {
- register int line;
- register LINEDESC *k;
-
- defalt (Curln, Curln);
-
- if (Line1 <= 0)
- {
- *status = ERR;
- Errcode = EORANGE;
- return;
- }
-
- *status = OK;
- line = 0;
- k = Line0;
-
- do {
- line++;
- k = NEXTLINE(k);
- if (line == Line2)
- k -> Markname = kname;
- else if (k -> Markname == kname)
- k -> Markname = DEFAULTNAME;
- } while (line < Lastln);
-
- return;
- }
-
-
- /* draw_box --- draw or erase a box at coordinates in command line */
-
- int draw_box (lin, i)
- char lin[];
- int *i;
- {
- register int left, right, col, len;
- int junk;
- int ctoi (), strcmp (), inject (), delete ();
- register LINEDESC *k;
- LINEDESC *getind (), *gettxt ();
- char text[MAXLINE];
- char kname, ch;
-
- left = ctoi (lin, i);
- if (left <= 0 || left > MAXLINE)
- {
- Errcode = EBADCOL;
- return (ERR);
- }
-
- if (lin[*i] == ',')
- {
- (*i)++;
- SKIPBL (lin, *i);
- right = ctoi (lin, i);
- if (right <= 0 || right >= MAXLINE || left > right)
- {
- Errcode = EBADCOL;
- return (ERR);
- }
- }
- else
- right = left;
-
- SKIPBL (lin, *i);
- if (lin[*i] == '\n')
- ch = ' ';
- else
- ch = lin[(*i)++];
-
- if (lin[*i] != '\n')
- {
- Errcode = EEGARB;
- return (ERR);
- }
-
- if (Line1 <= 0)
- {
- Errcode = EORANGE;
- return (ERR);
- }
-
- for (Curln = Line1; Curln <= Line2; Curln++)
- {
- k = gettxt (Curln);
- len = k -> Lineleng;
- move_ (Txt, text, len);
-
- if (text[len - 2] == '\n')
- col = len - 1;
- else
- col = len;
- while (col <= right)
- {
- text[col - 1] = ' ';
- col++;
- }
- text[col - 1] = '\n';
- text[col] = EOS;
-
- if (Curln == Line1 || Curln == Line2)
- for (col = left; col <= right; col++)
- text[col - 1] = ch;
- else
- {
- text[left - 1] = ch;
- text[right - 1] = ch;
- }
-
- if (strcmp (text, Txt) != 0)
- {
- kname = k -> Markname;
- if (delete (Curln, Curln, &junk) == ERR
- || inject (text) == ERR)
- return (ERR);
- k = getind (Curln);
- k -> Markname = kname;
- Buffer_changed = YES;
- }
- }
-
- Curln = Line1; /* move to top of box */
- if (First_affected > Curln)
- First_affected = Curln;
- adjust_window (Curln, Curln);
- updscreen ();
-
- return (OK);
- }
-
-
- /* dfltsopt --- set the 's' option to the extension on the file name */
-
- dfltsopt (name)
- char name[];
- {
- int i;
- int strlen (), dosopt ();
-
- for (i = strlen (name) - 1; i >= 0; i--)
- if (name[i] == '.')
- {
- dosopt (&name[i + 1]);
- break;
- }
- if (i < 0)
- dosopt ("");
- }
-
-
-
- /* doshell --- escape to the Shell to run one or more Unix commands */
-
- /*
- ** emulate vi: if running just a shell, redraw the screen as
- ** soon as the shell exits. if running a program, let the user
- ** redraw the screen when he/she is ready.
- **
- ** also emulate USG Unix 5.0 ed: a ! as the first character is
- ** replaced by the previous shell command; an unescaped % is replaced
- ** by the saved file name. The expanded command is echoed.
- */
-
- #ifdef BSD
- #define DEFAULT_PATH "/bin/csh"
- #define DEF_SHELL "csh"
- #else
- #define DEFAULT_PATH "/bin/sh"
- #define DEF_SHELL "sh"
- #endif
-
- int doshell (lin, pi)
- char lin[];
- int *pi;
- {
- int forkstatus, childstatus;
- int (*save_quit)(), (*save_int)();
- int int_hdlr ();
- int (*signal())();
- int i, auto_redraw;
- char *path, *name, *p, *getenv ();
- char new_command[MAXLINE];
- int j, k;
- static char sav_com[MAXLINE] = "";
- int expanded = NO;
-
- if (Nlines == 0) /* use normal 'ed' behavior */
- {
- tflush (); /* flush out the terminal output */
- position_cursor (Nrows - 1, 0); /* bottom left corner */
-
- if ((p = getenv ("SHELL")) == NULL || strcmp (p, DEFAULT_PATH) == 0)
- {
- path = DEFAULT_PATH;
- name = DEF_SHELL; /* default */
- }
- #ifdef BSD
- /* on Berkeley systems, check the other shell */
- else if (strcmp (p, "/bin/sh") == 0)
- {
- path = "/bin/sh";
- name = "sh";
- }
- #endif
- else
- {
- if (p[0] == '/') /* full pathname there */
- {
- /* work backwards to find just name */
- path = p;
- i = strlen (p);
- while (p[i] != '/')
- i--;
- i++; /* skip '/' */
- name = &p[i];
- }
- else
- {
- char buf[MAXLINE];
-
- sprintf (buf, "unknown shell, using %s",
- DEF_SHELL);
- remark (buf);
- path = DEFAULT_PATH;
- name = DEF_SHELL;
- }
- }
-
- auto_redraw = (lin[*pi] == '\n') ? YES : NO;
-
- /* build command, checking for leading !, and % anywhere */
- if (lin[*pi] == '!')
- {
- if (sav_com[0] != EOS)
- {
- for (j = 0; sav_com[j] != EOS; j++)
- new_command[j] = sav_com[j];
- if (new_command[j-1] == '\n')
- j--;
- (*pi)++;
- expanded = YES;
- }
- else
- {
- Errcode = ENOCMD;
- return (ERR);
- }
- }
- else
- j = 0;
-
- for (i = *pi; lin[i] != EOS; i++)
- {
- if (lin[i] == ESCAPE)
- {
- if (lin[i+1] != '%')
- {
- new_command[j++] = ESCAPE;
- new_command[j++] = lin[++i];
- }
- else
- new_command[j++] = lin[++i];
- }
- else if (lin[i] == '%')
- {
- for (k = 0; Savfil[k] != EOS; k++)
- new_command[j++] = Savfil[k];
- expanded = YES;
- }
- else
- new_command[j++] = lin[i];
- }
-
- if (new_command[j-1] == '\n')
- j--;
- new_command[j] = EOS;
-
- strcpy (sav_com, new_command); /* save it */
-
- ttynormal ();
- #ifndef HARD_TERMS
- t_exit ();
- #endif
- write (1, "\n\n", 2); /* clear out a line */
-
- forkstatus = fork();
- if (forkstatus == -1) /* the fork failed */
- {
- ttyedit ();
- #ifndef HARD_TERMS
- t_init ();
- #endif
- Errcode = ECANTFORK;
- return ERR;
- }
-
- if (forkstatus == 0) /* we're in the child process */
- {
- signal (SIGINT, SIG_DFL);
- signal (SIGQUIT, SIG_DFL);
- #ifdef BSD
- if (strcmp (name, "sh") != 0) /* not /bin/sh */
- signal (SIGTSTP, SIG_DFL);
- else
- signal (SIGTSTP, SIG_IGN);
- #endif
- if (auto_redraw) /* no params; run a shell */
- {
- execl (path, name, 0);
- _exit (RETERR); /* exec failed, notify parent */
- }
- else
- {
- if (expanded) /* echo it */
- printf ("%s\n", new_command);
-
- execl (path, name, "-c", new_command, 0);
- _exit (RETERR);
- }
- }
-
- /* we're in the parent process here */
- save_int = signal (SIGINT, SIG_IGN); /* ignore interrupts */
- save_quit = signal (SIGQUIT, SIG_IGN);
- while (wait (&childstatus) != forkstatus)
- ;
- save_int = signal (SIGINT, save_int); /* catch interupts */
- save_quit = signal (SIGQUIT, save_quit);
- write (1, "\n\n", 2); /* clear out some message space */
- Currow = Nrows - 1;
- Curcol = 0;
- if ((childstatus >> 8) != 0)
- {
- ttyedit ();
- #ifndef HARD_TERMS
- t_init ();
- #endif
- Errcode = ENOSHELL;
- return ERR;
- }
-
- /* a la vi: */
- if (! auto_redraw)
- {
- int c;
-
- printf ("type return to continue: ");
- while ((c = getchar()) != '\n' && c != EOF)
- ;
- }
-
- ttyedit ();
- #ifndef HARD_TERMS
- t_init ();
- #endif
- restore_screen ();
-
- return OK;
- }
-
- else
- remark ("Not implemented yet");
-
- return OK;
- }
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
-
-